package com.harmay.center.monitor.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import redis.clients.jedis.util.Pool;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Zuper
 * @version 1.0
 * @date 2022/6/16 11:28
 */
@Slf4j
public class RedisProxy {
    public static final int DAY_SECOND = 60 * 60 * 24;

    public static final int HOUR_SECOND = 60 * 60;

    @Autowired
    private Pool<Jedis> jedisPool;

    public void setJedisPool(Pool<Jedis> jedisPool) {
        this.jedisPool = jedisPool;
    }

    public Pool<Jedis> getJedisPool() {
        return jedisPool;
    }

    /*
     * string
     */
    public boolean exists(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.exists(key);
        }
    }

    public boolean exists(String key, String field) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hexists(key, field);
        }
    }

    /**
     * 保存Object
     *
     * @param object
     * @param key
     * @param seconds
     */
    public void saveObject(Object object, String key, int seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 二进制 IO 输出流
            ByteArrayOutputStream os = null;
            ObjectOutputStream oos = null;
            try {
                os = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(os);
                oos.writeObject(object); // 二进制数据
                byte[] b = os.toByteArray();
                // 存入二进制数据到Redis缓存中
                jedis.set(key.getBytes(), b);
                if (seconds > 0) {
                    jedis.expire(key, seconds);
                }
            } catch (Exception e) {
                log.error("保存redis对象出错", e);
            } finally {
                try {
                    os.close();
                    oos.close();
                } catch (Exception e2) {
                }
            }
        }

    }

    /**
     * 取缓存中的list集合对象
     *
     * @param key
     * @param clazz
     * @param seconds
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T getObject(String key, Class<T> clazz, int seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 二进制 IO 输入流
            ByteArrayInputStream is = null;
            ObjectInputStream ois = null;
            try {
                // 从缓存中取二进制数据
                byte[] b = jedis.get(key.getBytes());
                is = new ByteArrayInputStream(b);
                ois = new ObjectInputStream(is);
                // 把二进制转换成T指定类型的集合
                return (T) ois.readObject();
            } catch (Exception e) {
                log.error("获取redis对象出错", e);
            } finally {
                try {
                    is.close();
                    ois.close();
                } catch (Exception e2) {
                }
                if (seconds > 0) {
                    jedis.expire(key, seconds);
                }
            }
            return null;
        }

    }

    /**
     * 取缓存中的list集合对象
     *
     * @param key
     * @param clazz
     * @param seconds
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> getList(String key, Class<T> clazz, int seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 二进制 IO 输入流
            ByteArrayInputStream is = null;
            ObjectInputStream ois = null;
            try {
                // 从缓存中取二进制数据
                byte[] b = jedis.get(key.getBytes());
                is = new ByteArrayInputStream(b);
                ois = new ObjectInputStream(is);
                // 把二进制转换成T指定类型的集合
                return (List<T>) ois.readObject();

            } catch (Exception e) {
                log.error("获取redis数组对象出错", e);
            } finally {
                try {
                    is.close();
                    ois.close();
                } catch (Exception e2) {
                }
                if (seconds > 0) {
                    jedis.expire(key, seconds);
                }
            }
            return null;
        }
    }

    public Long incr(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.incr(key);
        }
    }

    public Long incr(String key, long delta) {
        try (Jedis jedis = jedisPool.getResource()) {
            if (delta < 0) {
                throw new RuntimeException("递增因子必须大于0");
            }
            return jedis.incrBy(key, delta);
        }
    }

    public void expire(String key, int seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.expire(key, seconds);
        }
    }

    public void expire(byte[] key, int seconds) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.expire(key, seconds);
        }
    }

    public byte[] get(byte[] key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.get(key);
        }
    }

    public String get(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.get(key);
        }
    }

    public byte[] dump(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.dump(key);
        }
    }

    public String restore(String key, int ttl, byte[] dump) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.restore(key, ttl, dump);
        }
    }

    public void set(byte[] key, byte[] data) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.set(key, data);
        }
    }

    public void set(String key, String data) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.set(key, data);
        }
    }

    public void del(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.del(key);
        }
    }

    public void del(String... keys) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.del(keys);
        }
    }

    public void del(byte[] key) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.del(key);
        }
    }

    /*
     * set
     */
    public Long sadd(String key, String... members) {
        if (members.length == 0) {
            return 0L;
        }
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.sadd(key, members);
        }
    }

    public Long srem(String key, String... members) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.srem(key, members);
        }
    }

    public Set<String> smembers(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.smembers(key);
        }
    }

    public String spop(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.spop(key);
        }
    }

    public Boolean sismember(String key, String member) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.sismember(key, member);
        }
    }

    /*
     * orderd set
     */
    public Set<String> zrange(String key, long start, long end) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.zrange(key, start, end);
        }
    }

    public void zadd(String key, double score, String member) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.zadd(key, score, member);
        }
    }

    public Set<Tuple> zrangeWithScores(String key, long start, long end) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.zrangeWithScores(key, start, end);
        }
    }

    public Long zcard(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.zcard(key);
        }
    }

    public Long zcount(String key, double min, double max) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.zcount(key, min, max);
        }
    }

    /*
     * list
     */

    public String rpop(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.rpop(key);
        }
    }

    public byte[] rpop(byte[] key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.rpop(key);
        }
    }

    public void lpush(String key, String... strings) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.lpush(key, strings);
        }
    }

    public void lpush(byte[] key, byte[]... strings) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.lpush(key, strings);
        }
    }

    public void rpush(byte[] key, byte[]... strings) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.lpush(key, strings);
        }
    }

    public void ltrim(byte[] key, long start, long end) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.ltrim(key, start, end);
        }
    }

    /*
     * hash
     */

    public Long hdel(String key, String... fields) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hdel(key, fields);
        }
    }

    public String hget(String key, String field) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hget(key, field);
        }
    }

    public byte[] hget(byte[] key, byte[] field) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hget(key, field);
        }
    }

    public List<String> hmget(String key, String... fields) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hmget(key, fields);
        }
    }

    public List<byte[]> hmget(byte[] key, byte[]... fields) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hmget(key, fields);
        }
    }

    public void hset(String key, String field, String value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hset(key, field, value);
        }
    }

    public long hincr(String key, String field, long value) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hincrBy(key, field, value);
        }
    }

    public void hset(byte[] key, byte[] field, byte[] value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hset(key, field, value);
        }
    }

    public void hmset(String key, Map<String, String> hash) {
        if (hash == null || hash.isEmpty()) {
            return;
        }
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hmset(key, hash);
        }
    }

    public Map<String, String> hgetAll(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hgetAll(key);
        }
    }

    public Set<String> keys(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.keys(key);
        }
    }

    public Set<String> hkeys(String key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hkeys(key);
        }
    }

    public Map<byte[], byte[]> hgetAll(byte[] redisKey) {
        try (Jedis jedis = jedisPool.getResource()) {
            return jedis.hgetAll(redisKey);
        }
    }
}
